#include "Order.h"
#include <set>
#include "Album.h"
#include "mtm_ex4.h"
#include "mtmtest.h"
using namespace mtm;
using std::set;

namespace OrderTest {

void createTest() {
	// check invalid parameters
	ASSERT_THROWS(INVALID_ORDER_NUMBER, Order(-6));
	Order newOrder(10);
	// check object has correct init parameters.
	ASSERT_EQUALS(10, newOrder.getId());
	// check albums can be added to order.
	Album newAlbum(10, 44, 1989, 200, "best of yomamas", "yomama");
	ASSERT_NO_THROW(newOrder.addAlbum(newAlbum));
}

void addAlbumTest() {
	Order newOrder(10);
	Album newAlbum(10, 44, 1989, 200, "best of yomamas", "yomama");
	// check no exceptions for valid album add.
	ASSERT_NO_THROW(newOrder.addAlbum(newAlbum));
	// pay for the order.
	ASSERT_NO_THROW(newOrder.pay());
	// check album cannot be added to paid order.
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID, newOrder.addAlbum(newAlbum));

}

void removeAlbumTest() {
	Order newOrder(10);
	Album newAlbum(10, 44, 1989, 200, "best of yomamas", "yomama");
	// check no exceptions for valid album add.
	ASSERT_NO_THROW(newOrder.addAlbum(newAlbum));
	// check no exceptions for valid album remove.
	ASSERT_NO_THROW(newOrder.removeAlbum(newAlbum));
	// check album cannot be added to paid order.
	ASSERT_THROWS(ORDER_DOESNT_HAVE_ALBUM, newOrder.removeAlbum(newAlbum));
}

void getIdTest() {
	Order newOrder(10);

	ASSERT_EQUALS(10, newOrder.getId());
}

void getAlbumsTest() {
	// create a new order and insert some albums.
	Order newOrder(10);
	Album newAlbum1(10, 40, 1989, 200, "best of yomamas", "yomama");
	Album newAlbum2(13, 35, 1956, 200, "Oh mh god that's the funky shit",
			"Mr k");
	Album newAlbum3(19, 25, 2006, 200, "Brave sir lance'alot", "fridge magnet");

	newOrder.addAlbum(newAlbum1);
	newOrder.addAlbum(newAlbum2);
	newOrder.addAlbum(newAlbum3);
	// create a new list and populate with the same albums as order.
	List<Album> tempList;
	tempList.insert(newAlbum1);
	tempList.insert(newAlbum2);
	tempList.insert(newAlbum3);
	// get album list from new order and compare the two lists. should be equal.
	const List<Album> albums = newOrder.getAlbums();
	ASSERT_TRUE(tempList == albums);

}

void payTest() {
	Order newOrder(10);
	Album newAlbum1(10, 40, 1989, 200, "best of yomamas", "yomama");
	newOrder.addAlbum(newAlbum1);
	// pay for a newly created order with a single album.
	newOrder.pay();
	// confirm that no action can alter an already paid order.
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID, newOrder.pay());
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID,
			newOrder.addAlbum(newAlbum1));
	ASSERT_THROWS(ORDER_WAS_ALREADY_PAID, newOrder.removeAlbum(newAlbum1));
}

void getOrderReportTest() {
	Order newOrder(10);
	Album newAlbum1(10, 40, 1989, 200, "best of yomamas", "yomama");
	newOrder.addAlbum(newAlbum1);
	// check getOrderReport's output string is as expected.
	ASSERT_EQUALS(getOrderHeaderString(10,15,1,false)
			+ getAlbumMinimalString("best of yomamas","yomama",1989,40)
			,newOrder.getOrderReport(15));
	// pay for the order and check for false/true difference in output string.
	newOrder.pay();

	ASSERT_EQUALS(getOrderHeaderString(10,15,1,true)
				+ getAlbumMinimalString("best of yomamas","yomama",1989,40)
				,newOrder.getOrderReport(15));
}

void OrderSortTest() {
	set<Order, Order::SortById> orders;
	orders.insert(Order(1));
	orders.insert(Order(10));
	orders.insert(Order(2));
	orders.insert(Order(7));
	int sortedIds[] = { 1, 2, 7, 10 };
	int i = 0;
	for (const Order& order : orders) {
		ASSERT_EQUALS(sortedIds[i++],order.getId());
	}
}

}

/* uncomment to run tests, or copy the relevant code */
//using namespace OrderTest;
//int main() {
//	RUN_TEST(createTest);
//	RUN_TEST(addAlbumTest);
//	RUN_TEST(removeAlbumTest);
//	RUN_TEST(getIdTest);
//	RUN_TEST(getAlbumsTest);
//	RUN_TEST(payTest);
//	RUN_TEST(getOrderReportTest);
//	RUN_TEST(OrderSortTest);
//}

